package com.huaxinzhi.print;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;

import androidx.annotation.NonNull;

import com.smasher.core.log.ToastUtil;
import com.smasher.core.other.ApplicationContext;
import com.smasher.core.other.WeakReferenceHandler;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class PrintHelper implements Handler.Callback {


    private static final String TAG = "PrintHelper";

    /**
     * 连接状态断开
     */
    private static final int CONN_STATE_DISCONN = 0x007;
    private static final int CONN_PRINTER = 0x12;

    /**
     * 使用打印机指令错误
     */
    private static final int PRINTER_COMMAND_ERROR = 0x008;


    /**
     * ESC查询打印机实时状态指令
     */
    private byte[] esc = {0x10, 0x04, 0x02};
    /**
     * CPCL查询打印机实时状态指令
     */
    private byte[] cpcl = {0x1b, 0x68};
    /**
     * TSC查询打印机状态指令
     */
    private byte[] tsc = {0x1b, '!', '?'};


    private int printcount = 0;
    private int counts;
    private boolean continuityprint = false;


    /**
     * 判断打印机所使用指令是否是ESC指令
     */
    private int id = 0;

    private ThreadPool threadPool;

    private WeakReferenceHandler mHandler;

    private List<IChannel> observers;


    public PrintHelper() {
        observers = new ArrayList<>();
        mHandler = new WeakReferenceHandler(this);
    }


    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void sendContinuityPrint() {
        ThreadPool.getInstantiation().addSerialTask(new Runnable() {
            @Override
            public void run() {
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] != null
                        && DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
                    ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder("MainActivity_sendContinuity_Timer");
                    ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1, threadFactoryBuilder);
                    scheduledExecutorService.schedule(threadFactoryBuilder.newThread(new Runnable() {
                        @Override
                        public void run() {
                            counts--;
                            if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.ESC) {
                                DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendDataImmediately(PrintContent.getReceipt());
                            } else if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.TSC) {
                                DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendDataImmediately(PrintContent.getLabel());
                            } else {
                                DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendDataImmediately(PrintContent.getCPCL());
                            }
                        }
                    }), 1000, TimeUnit.MILLISECONDS);
                }
            }
        });
    }


    /**
     * 打印标签例子
     * <p>
     * //@param view
     *
     */
    public void btnLabelPrint(JSONObject json) {//View view
        threadPool = ThreadPool.getInstantiation();
        threadPool.addSerialTask(new Runnable() {
            @Override
            public void run() {
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null ||
                        !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
                    mHandler.obtainMessage(CONN_PRINTER).sendToTarget();
                    return;
                }
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.TSC) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendDataImmediately(LabelContent.getLabel(json));//PrintContent.getLabel()
                } else {
                    mHandler.obtainMessage(PRINTER_COMMAND_ERROR).sendToTarget();
                }
            }
        });
    }

    public void btnLabelMatrix(View view) {
        threadPool = ThreadPool.getInstantiation();
        threadPool.addSerialTask(new Runnable() {
            @Override
            public void run() {
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null ||
                        !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
                    mHandler.obtainMessage(CONN_PRINTER).sendToTarget();
                    return;
                }
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.TSC) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendDataImmediately(PrintContent.getNewCommandToPrintQrcode());
                } else {
                    mHandler.obtainMessage(PRINTER_COMMAND_ERROR).sendToTarget();
                }
            }
        });
    }


    /**
     * 打印机状态查询，部分打印机没有返回值，则无法收到返回，
     *
     * @param view view
     */
    public void btnPrinterState(View view) {
        //打印机状态查询
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null ||
                !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
            //ToastUtils.showLongToast(getString(R.string.str_cann_printer));
            return;
        }
        ThreadPool.getInstantiation().addSerialTask(new Runnable() {
            @Override
            public void run() {
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.ESC) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendByteDataImmediately(esc);
                } else if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.TSC) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendByteDataImmediately(tsc);
                } else if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.CPCL) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendByteDataImmediately(cpcl);
                }
            }
        });
    }


    public void serialConnectOri(int baudrate, String path) {

        closeport();
        if (baudrate != 0 && !TextUtils.isEmpty(path)) {
            //初始化DeviceConnFactoryManager
            new DeviceConnFactoryManager.Build()
                    //设置连接方式
                    .setConnMethod(DeviceConnFactoryManager.CONN_METHOD.SERIAL_PORT)
                    .setId(id)
                    //设置波特率
                    .setBaudrate(baudrate)
                    //设置串口号
                    .setSerialPort(path)
                    .build();
            //打开端口
            //打开端口
            threadPool = ThreadPool.getInstantiation();
            threadPool.addSerialTask(new Runnable() {
                @Override
                public void run() {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].openPort();
                }
            });
        }
    }


    /**
     * 断开连接
     */
    public void btnDisConn() {
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null || !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
//            Utils.toast(this, getString(R.string.str_cann_printer));
            return;
        }
        mHandler.obtainMessage(CONN_STATE_DISCONN).sendToTarget();
    }


    /**
     * 重新连接回收上次连接的对象，避免内存泄漏
     */
    public void closeport() {
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] != null && DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort != null) {
            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].reader.cancel();
            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort.closePort();
            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort = null;
        }
    }


    /**
     * 获取当前连接设备信息
     *
     * @return
     */
    public String getConnDeviceInfo() {
        String str = "";
        DeviceConnFactoryManager deviceConnFactoryManager = DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id];
        if (deviceConnFactoryManager != null
                && deviceConnFactoryManager.getConnState()) {
            if ("USB".equals(deviceConnFactoryManager.getConnMethod().toString())) {
                str += "USB\n";
                str += "USB Name: " + deviceConnFactoryManager.usbDevice().getDeviceName();
            } else if ("WIFI".equals(deviceConnFactoryManager.getConnMethod().toString())) {
                str += "WIFI\n";
                str += "IP: " + deviceConnFactoryManager.getIp() + "\t";
                str += "Port: " + deviceConnFactoryManager.getPort();
//                checkWifiConnThread = new CheckWifiConnThread(deviceConnFactoryManager.getIp(), mHandler);//开启监听WiFi线程
//                checkWifiConnThread.start();
            } else if ("BLUETOOTH".equals(deviceConnFactoryManager.getConnMethod().toString())) {
                str += "BLUETOOTH\n";
                str += "MacAddress: " + deviceConnFactoryManager.getMacAddress();
            } else if ("SERIAL_PORT".equals(deviceConnFactoryManager.getConnMethod().toString())) {
                str += "SERIAL_PORT\n";
                str += "Path: " + deviceConnFactoryManager.getSerialPortPath() + "\t";
                str += "Baudrate: " + deviceConnFactoryManager.getBaudrate();
            }
        }
        return str;
    }

    @Override
    public boolean handleMessage(@NonNull Message msg) {
        switch (msg.what) {
            case CONN_STATE_DISCONN:
                //断开连接
                DeviceConnFactoryManager deviceConnFactoryManager = DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id];
                if (deviceConnFactoryManager != null && deviceConnFactoryManager.getConnState()) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].closePort(id);
                    handleEvent(CONN_STATE_DISCONN, "");

                }
                break;
            case PRINTER_COMMAND_ERROR:
                //打印机指令错误
                handleEvent(PRINTER_COMMAND_ERROR, "");

                break;
            case CONN_PRINTER:
                //未连接打印机
                handleEvent(CONN_PRINTER, "");

                break;
            case Constant.tip:
                String str = (String) msg.obj;
                Context context = ApplicationContext.getInstance();
                ToastUtil.info(context,str);
                break;
            default:
                break;
        }
        return false;
    }


    public void print() {
        if (counts >= 0) {
            if (continuityprint) {
                printcount++;
                //ToastUtils.showLongToast(getString(R.string.str_continuityprinter) + " " + printcount);
            }
            if (counts != 0) {
                sendContinuityPrint();
            } else {
                continuityprint = false;
            }
        }
    }


    public void close() {
        DeviceConnFactoryManager.closeAllPort();
        if (threadPool != null) {
            threadPool.stopThreadPool();
        }
    }

    public void addObserver(IChannel observer) {
        observers.add(observer);
    }

    public void removeObserver(IChannel observer) {
        observers.remove(observer);
    }


    private void handleEvent(int action, String message) {

        if (observers.size() <= 0) {
            return;
        }

        for (IChannel observer : observers) {
            if (observer != null) {

                switch (action) {
                    case CONN_STATE_DISCONN:
                        observer.onDisConnected();
                        break;
                    case PRINTER_COMMAND_ERROR:
                        observer.onPrintError();
                        break;
                    case CONN_PRINTER:
                        observer.unConnect();
                        break;
                    default:
                        break;
                }

            }
        }
    }
}
